package com.sharp.core.voxel;

import com.sharp.core.graphics.Light;
import com.sharp.core.math.Vec3;
import com.sharp.core.raytrace.Intersection;
import com.sharp.core.raytrace.Ray;
import com.sharp.core.utils.Vars;

public class GridVoxelScene extends VoxelHolder {

	private VoxelArray map;
	private float voxelSize;
	
	public GridVoxelScene(int w, int h, int z, float voxelSize) {
		this.map = new VoxelArray(w, h, z);
		this.voxelSize = voxelSize;
		Vars.set(Vars.INTERSECT_PER_FRAME, 0);
	}
	
	
	
	@Override
	public void addObject(VoxelObject p) {
		VoxelArray arr = (VoxelArray) p.getData();
		map.merge(arr, (int)p.getPos().getX(), (int)p.getPos().getY(), (int)p.getPos().getZ());
	}


	@Override
	public void addLight(Light p) {
	}

	@Override
	public VoxelIntersection findIntersection(Ray ray) {
		int mapX = (int) ray.getOrigin().getX();
		int mapY = (int) ray.getOrigin().getY();
		int mapZ = (int) ray.getOrigin().getZ();
		
		float rayDirX  = ray.getDir().getX();
		float rayDirY  = ray.getDir().getY();
		float rayDirZ  = ray.getDir().getZ();
		
		float rayPosX  = ray.getOrigin().getX();
		float rayPosY  = ray.getOrigin().getY();
		float rayPosZ  = ray.getOrigin().getZ();

		
		float maxX, maxY, maxZ;
		int stepX, stepY, stepZ;
		
		if ( rayDirX < 0 ) {
			stepX = -1;
			maxX = (rayPosX - mapX);
		} else {
			stepX = 1;
			maxX = (mapX+1-rayPosX);
		}
		
		if ( rayDirY < 0 ) {
			stepY = -1;
			maxY = (rayPosY - mapY);
		} else {
			stepY = 1;
			maxY = (mapY+1-rayPosY);
		}
		
		if ( rayDirZ < 0 ) {
			stepZ = -1;
			maxZ = (rayPosZ - mapZ);
		} else {
			stepZ = 1;
			maxZ = (mapZ+1-rayPosZ);
		}
		
		float deltaX = 1/rayDirX * stepX;	// függölegestől függelegesik
		float deltaY = 1/rayDirY * stepY; 	// vizszintestől vizszintesig
		float deltaZ = 1/rayDirZ * stepZ;
		maxX *= deltaX;
		maxY *= deltaY;
		maxZ *= deltaZ;
		
		Voxel voxel = null;
		Voxel.Side side = null;
		while( true ) {
			//Vars.set(Vars.INTERSECT_PER_FRAME, Vars.<Integer>get(Vars.INTERSECT_PER_FRAME)+1);
			Vars.g++;
			if ( maxX < maxY ) {
				if ( maxZ < maxX ) {
					maxZ += deltaZ;
					mapZ += stepZ;
					side = Voxel.Side.FRONT;
				} else {
					maxX += deltaX;
					mapX += stepX;
					side = Voxel.Side.LEFT;
				}
			} else if ( maxZ < maxY ) {
					maxZ += deltaZ;
					mapZ += stepZ;
					side = Voxel.Side.FRONT;
			} else {
					maxY += deltaY;
					mapY += stepY;
					side = Voxel.Side.TOP;
			}
			if ( mapX >= map.getWidth() || mapX < 0 || 
					mapY >= map.getHeight() || mapY < 0 ||
					mapZ >= map.getDepth() || mapZ < 0 ) {
				break;
			}
			if ( (voxel=map.getVoxel(mapX, mapY, mapZ)) != null )
				break;
		}
		if ( voxel == null )
			return null;
		VoxelIntersection inter = new VoxelIntersection(this);
		inter.setVoxel(voxel);
		inter.setSide(side);
		inter.setPos(new Vec3( mapX, mapY, mapZ ));
		return inter;
	}

	@Override
	public Iterable<Light> getLights() {
		return null;
	}

	@Override
	public boolean isIntersected(Ray ray) {
		return false;
	}

	@Override
	public boolean isVisible(Intersection from, Light l) {
		return false;
	}
}
